home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1996 / MacHack 1996.toast / Hacks / Hacks ’89 / gadlife / source (ugly) / patch.dialog.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-05-08  |  5.6 KB  |  185 lines  |  [TEXT/KAHL]

  1. #include "main.h"
  2. #include "patch.h"
  3.  
  4. static int         modalActed = 0, modalTrapOn = 0;
  5. static long        oldModal, oldFilterProc = NULL;
  6.  
  7. /*******************************************************
  8. *                                                                *
  9. *    isButtonControl is *very* dangerous.  It reads the high 8 bits of the defProc    *
  10. *    pointer to figure out what type of control this is.  This could be rewritten to    *
  11. *    try getResource on the CDEF resource and compare handles or something.        *
  12. *                                                                *
  13. *******************************************************/
  14.  
  15. isButtonControl( theControl )
  16.     ControlHandle    theControl;
  17. {    
  18.     return( HiWord(( **theControl ).contrlDefProc ) < 0x1000 && !( **theControl ).contrlHilite );
  19. }    
  20.  
  21. /*******************************************************
  22. *                                                                *
  23. *    FindButton is used in the dialog event filters.  If a command-letter combination    *
  24. *    is entered in a dialog while gadlife is running, the program attempts to find a    *
  25. *    button with that letter as its first character.  If it finds one, it kills the event    *
  26. *    and returns an itemHit in the appropriate button.  If there are duplicates, none    *
  27. *    are returned, and the event is passed through.  This may end up    causing        *
  28. *    problems with certain DA's which have command-key equivalents for buttons    *
  29. *    which do not correspond to first letters of the buttons, but this seems unlikely.    *
  30. *                                                                *
  31. *******************************************************/
  32.  
  33. findButton( theDialog, theChar, modifiers )
  34.     DialogPtr        theDialog;
  35.     char            theChar;
  36.     int            modifiers;
  37. {
  38.     ControlHandle    item = 0, control, theControl;
  39.     Rect            box;
  40.     long            finalTicks;
  41.     int            itemNo = 0, type, found;
  42.     
  43.     if( theChar == ETX || theChar == CR ) {
  44.         itemNo = (( DialogPeek )theDialog )->aDefItem;
  45.         GetDItem( theDialog, itemNo, &type, &item, &box );
  46.     } else if( modifiers & cmdKey ) {
  47.         if( theChar >= 'a' && theChar <= 'z' ) theChar += 'A'-'a';
  48.         control = (( WindowPeek )theDialog )->controlList;
  49.         for( found = 0; control && found < 2; control = ( **control ).nextControl )
  50.             if( isButtonControl( control ) && ( **control ).contrlTitle[ 1 ] == theChar ) {
  51.                 theControl = control;
  52.                 ++found;
  53.             }
  54.         if( found == 1 )
  55.             while( item != theControl )
  56.                 GetDItem( theDialog, ++itemNo, &type, &item, &box );
  57.     }
  58.     if( itemNo ) {
  59.         HiliteControl( item, inButton );
  60.         doDelay( buttonDelay, &finalTicks );
  61.         HiliteControl( item, 0 );
  62.     }
  63.     return( itemNo );
  64. }
  65.  
  66. /*******************************************************
  67. *                                                                *
  68. *    FakeFilter simply replaces the usual default event filter with one which allows    *
  69. *    backgrounding and catches keyboard equivalents (using findButton).            *
  70. *                                                                *
  71. *******************************************************/
  72.  
  73. pascal int fakeFilter( theDialog, theEvent, itemHit )
  74.     DialogPtr        theDialog;
  75.     EventRecord    *theEvent;
  76.     int            *itemHit;
  77. {
  78.     Rect            box;
  79.     ControlHandle    item;
  80.     int            type, result = 0;
  81.     char            theChar;
  82.  
  83.     doBackground( nothingElseToDo, noGray, NULL );
  84.     if( theEvent->what == keyDown ) {
  85.         theChar =     theEvent->message & charCodeMask;
  86.         if( *itemHit = findButton( theDialog, theChar, theEvent->modifiers ))
  87.             result = -1;
  88.     }
  89.     return( result );
  90. }
  91.  
  92. /*******************************************************
  93. *                                                                *
  94. *    PassFilter usually passes the filter call through to the original filter.  If there    *
  95. *    is a keyboard shortcut, it is flagged and returned without calling the original    *
  96. *    filter.  This might cause a problem with a filter that does more than just filter    *
  97. *    events.  To fix, could instead pass a mouse-down and then patch TrackControl    *
  98. *    or something to immediately return true.                                *
  99. *                                                                *
  100. *******************************************************/
  101.  
  102. pascal int passFilter( theDialog, theEvent, itemHit )
  103.     DialogPtr        theDialog;
  104.     EventRecord    *theEvent;
  105.     int            *itemHit;
  106. {
  107.     char            theChar;
  108.     
  109.     doBackground( someElseToDo, noGray, NULL );
  110.     if( theEvent->what == keyDown ) {
  111.         theChar = theEvent->message & charCodeMask;
  112.         if( *itemHit = findButton( theDialog, theChar, theEvent->modifiers ))
  113.             return( -1 );
  114.     }
  115.     asm {
  116.             unlk        a6
  117.             move.l    oldFilterProc,a0
  118.             jmp        (a0)
  119.     }
  120. }
  121.  
  122. /*******************************************************
  123. *                                                                *
  124. *    If the modal dialog patches are not already installed, it doModalPatch installs    *
  125. *    them.  If there is no filterProc, fakeFilter is installed.  If a filterProc is given,    *
  126. *    passFilter is installed as a filter filter.  This is where the problem is - If there    *
  127. *    are nested dialogs, with more than one filterproc, after the child closes the    *
  128. *    parent will still use the child's filterproc.  I'm not quite sure how to fix this.    *
  129. *                                                                *
  130. *******************************************************/
  131.  
  132. pascal doModalPatch( theFilter, theHit )
  133.     long        theFilter;
  134.     int        *theHit;
  135.     {
  136.     int        temp;
  137.     asm {
  138.         movem.l    d0-d7/a1-a5,-(sp)
  139.         move.l    CurrentA5,a5
  140.     }
  141.     if( !modalActed ) {
  142.         installWaitTrap();
  143.         installPopUpTrap();
  144.         modalActed = 1;
  145.     }
  146.     if( theFilter ) {
  147.         oldFilterProc = theFilter;
  148.         theFilter = (long)passFilter;
  149.     } else    theFilter = (long)fakeFilter;
  150.     asm {
  151.         move.l    oldModal,a0
  152.         movem.l    (sp)+,d0-d7/a1-a5
  153.         unlk        a6
  154.         jmp        (a0)
  155.     }
  156. }
  157.  
  158. /*******************************************************
  159. *                                                                *
  160. *    These are horrible, and need fixing.                                    *
  161. *                                                                *
  162. *******************************************************/
  163.  
  164. installModalTrap()
  165.     {
  166.     if( !modalTrapOn )
  167.         {
  168.         oldModal = NGetTrapAddress( ModalTrapNum, ToolTrap );
  169.         NSetTrapAddress( doModalPatch, ModalTrapNum, ToolTrap );
  170.         modalActed = 0;
  171.         }
  172.     ++modalTrapOn;
  173.     }
  174.     
  175. removeModalTrap() {
  176.     if( modalTrapOn == 1 ) {
  177.         NSetTrapAddress( oldModal, ModalTrapNum, ToolTrap );
  178.         if( modalActed ) {
  179.             removeWaitTrap();
  180.             removePopUpTrap();
  181.             modalActed = 0;
  182.         }
  183.     }
  184.     if( modalTrapOn > 0 ) --modalTrapOn;
  185. }